#ifndef ObjectTable_First
#define ObjectTable_First
#ifdef __GNUG__
#pragma interface
#endif

#include "Object.h"
#include "Iterator.h"

class ObjectTableIter;
class OrdCollection;
class Class;

//---- ObjectTable -------------------------------------------------------------
//         this class registers all instances of Object or its subclasses
//         in a hash table

class ObjectTable : public Object {
public:
	MetaDef(ObjectTable);

	~ObjectTable();
	static void Add(Object*);
	static void Remove(Object*);
	static void UpdateInstCount(bool heaponly= FALSE);
	static bool PtrIsValid(Object*);
	static void *CheckPtrAndWarn(const char *msg, void*);
	static int Instances();         // return total number of instances
	static void InstanceStatistics();
	static void Terminate();
	static Object *SomeInstance(Class*);
	static Object *SomeMember(Class*);

private:
friend ObjectTableIter;
	ObjectTable();

	static bool HighWaterMark();
	static void Expand(int newsize);
	static int FindElement(Object*);
	static void FixCollisions(int index);

	static Object *lastobject;
	static bool died;
	static Class **tab;
	static Object **table;
	static int size, tally, iterlevel;
	static OrdCollection *delayed; // insertions while an iterator is active are delayed
	static OrdCollection *rdelayed;
	//---- statistics
	static int convoi, seed;
	static long cumconvoi;
};

inline bool ObjectTable::HighWaterMark()
	{ return (bool) (tally >= ((3*size)/4)); }
inline bool ObjectTable::PtrIsValid(Object *op)
	{ return table ? (table[FindElement(op)] != 0) : TRUE; }
inline int ObjectTable::Instances()
	{ return tally; }


extern "C" void gIsA(Object *op);

//---- ObjectTableIter ---------------------------------------------------------

class ObjectTableIter : public Iterator {
	int cursor;         // for iterating
	Class *fromClass;   // looking for instances of class in operator()()
	bool members;       // return only direct members of a clas in "   "
public:
	ObjectTableIter(Class *cl= 0, bool members= TRUE);
	~ObjectTableIter();
	Object *operator()();
};

#endif

